from rest_framework.decorators import action
from rest_framework.viewsets import ViewSet, GenericViewSet
from utils.response import APIResponse
from .serializers import UserLoginSerializer, StudentClassSerializer, StudentRegisterSerializer, StudentListSerializer, \
    EditStudentSerializer, EditUserinfoSerializer
from .models import *
from .jwt_auth import JwtAuth
from .pagenate import CommonNumPagination
from .permissions import TeacherPermission, AdminPermission
from rest_framework.exceptions import APIException
from rest_framework.filters import OrderingFilter, SearchFilter
from django_filters.rest_framework import DjangoFilterBackend
from utils.views import CommonListModelMixin, CommonCreateModelMixin, CommonRetrieveModelMixin
import psutil
from paper.models import Paper, Title, Task
from django.db.models import Count
from redis import Redis
import os

redis = Redis(host='redis', port=6379)


# 注册登录视图
class LoginView(ViewSet):
    @action(methods=['POST'], detail=False)
    def login(self, request):
        ser = UserLoginSerializer(data=request.data, context={'request': request})
        ser.is_valid(raise_exception=True)
        token = ser.context.get('token')
        user_id = ser.context.get('user_id')
        icon = ser.context.get('icon')
        role = ser.context.get('role')
        username = ser.context.get('username')
        return APIResponse(token=token, username=username, id=user_id, icon=icon, role=role)

    @action(methods=['POST'], detail=False)
    def student_register(self, request):
        ser = StudentRegisterSerializer(data=request.data)
        ser.is_valid(raise_exception=True)
        return APIResponse()


# 用户资料相关视图
class EditUserinfoView(ViewSet):
    authentication_classes = [JwtAuth, ]

    @action(methods=["GET"], detail=False)
    def get_userinfo(self, request):
        user_id = request.query_params.get('user_id')
        user = Userinfo.objects.filter(pk=user_id).first()
        ser = EditUserinfoSerializer(instance=user)
        return APIResponse(result=ser.data)

    @action(methods=["POST"], detail=False)
    def update_userinfo(self, request):
        user_id = request.data.get('id')
        email = request.data.get('email')
        icon = request.data.get('icon')
        username = request.data.get('username')
        context = {'icon': icon, 'email': email, 'username': username, 'viewer': self, 'user_id': user_id}
        ser = EditUserinfoSerializer(data=request.data, context=context)
        ser.is_valid(raise_exception=True)
        return APIResponse()

    @action(methods=['POST'], detail=False)
    def change_pwd(self, request):
        old_password = request.data.get('old_password')
        if request.user.check_password(old_password):
            new_password = request.data.get('new_password')
            request.user.set_password(new_password)
            request.user.save()
        else:
            raise APIException('原密码错误')
        return APIResponse()

    @action(methods=['POST'], detail=False)
    def upload_avatar(self, request):
        return APIResponse()


# 学生班级视图
class StudentClassView(GenericViewSet, CommonCreateModelMixin, CommonListModelMixin, CommonRetrieveModelMixin):
    queryset = StudentClass.objects.all().order_by('-create_time')
    serializer_class = StudentClassSerializer
    pagination_class = CommonNumPagination
    # authentication_classes = [JwtAuth, ]
    # permission_classes = [TeacherPermission, ]


# 编辑学生班级
class EditStudentClassView(ViewSet):
    authentication_classes = [JwtAuth, ]
    permission_classes = [TeacherPermission, ]

    @action(methods=['POST'], detail=False)
    def del_class(self, request):
        if request.user.role != 2:
            raise APIException('只有管理员有删除权限')
        for class_id in request.data:
            StudentClass.objects.filter(pk=class_id).delete()
        return APIResponse()

    @action(methods=['POST'], detail=False)
    def update_class(self, request):
        class_id = request.data.get('id')
        class_name = request.data.get('name')
        if StudentClass.objects.filter(name=class_name):
            raise APIException('班级名称已存在')
        else:
            StudentClass.objects.filter(pk=class_id).update(name=class_name)
            return APIResponse()


# 学生列表视图
class StudentListView(GenericViewSet, CommonListModelMixin, CommonRetrieveModelMixin):
    queryset = Userinfo.objects.filter(role=0).order_by('student_class_id')
    serializer_class = StudentListSerializer
    authentication_classes = [JwtAuth, ]
    permission_classes = [TeacherPermission, ]
    pagination_class = CommonNumPagination
    filter_backends = [DjangoFilterBackend, SearchFilter]
    search_fields = ['username']
    filterset_fields = ['student_class']


# 编辑学生信息视图
class EditStudentView(ViewSet):
    authentication_classes = [JwtAuth, ]
    permission_classes = [TeacherPermission, ]

    @action(methods=['POST'], detail=False)
    def activate(self, request):
        student_id = request.data.get('student_id')
        is_active = Userinfo.objects.filter(pk=student_id).first().is_active
        if is_active:
            Userinfo.objects.filter(pk=student_id).update(is_active=0)
        else:
            Userinfo.objects.filter(pk=student_id).update(is_active=1)
        return APIResponse()

    @action(methods=['POST'], detail=False)
    def update_student(self, request):
        user_id = request.data.get('id')
        username = request.data.get('username')
        ser = EditStudentSerializer(data=request.data, context={'username': username, 'user_id': user_id})
        ser.is_valid(raise_exception=True)
        return APIResponse()

    @action(methods=['POST'], detail=False)
    def del_student(self, request):
        if request.user.role != 2:
            raise APIException('只有管理员有删除权限')
        for student_id in request.data:
            Userinfo.objects.filter(pk=student_id).delete()
        return APIResponse()


class TeacherIndexView(ViewSet):
    authentication_classes = [JwtAuth, ]
    permission_classes = [TeacherPermission, ]

    @action(methods=['GET'], detail=False)
    def server_status(self, request):
        cpu_per = psutil.cpu_percent(interval=1, percpu=True)
        max_per = max(cpu_per)
        memory_per = psutil.virtual_memory().percent
        return APIResponse(server_status={'cpu_per': max_per, 'memory_per': memory_per})

    @action(methods=['GET'], detail=False)
    def data_count(self, request):
        student_count = Userinfo.objects.filter(role=0).count()
        paper_count = Paper.objects.all().count()
        title_count = Title.objects.all().count()
        task_count = Task.objects.all().count()
        result = {'student_count': student_count, 'paper_count': paper_count, 'title_count': title_count,
                  'task_count': task_count}
        return APIResponse(result=result)

    @action(methods=['GET'], detail=False)
    def title_type(self, request):
        category = Title.objects.all().values('title_type').annotate(value=Count('id')).values('title_type', 'value')
        names = []
        scores = []
        try:
            res = Task.objects.all().order_by('-create_time').first().studentOfTask.all().order_by('-final_score')[0:5]
            for paper in res:
                names.append(paper.student.username)
                scores.append(paper.final_score)
        except Exception as e:
            pass
        for item in category:
            if item.get('title_type') == 0:
                item['name'] = '单选题'
            elif item.get('title_type') == 1:
                item['name'] = '多选题'
            elif item.get('title_type') == 2:
                item['name'] = '判断题'
            elif item.get('title_type') == 3:
                item['name'] = '简答题'
            item.pop('title_type')
        return APIResponse(result=category, names=names, scores=scores)


class VisitorView(ViewSet):
    @action(methods=['GET'], detail=False)
    def visitor(self, request):
        redis.incr('visitors')
        visitors = redis.get('visitors')
        return APIResponse(visitors=visitors)
